package dao

import (
	mysql "sems/database"
	"sems/model"
	"time"

	"go.uber.org/zap"
)

func GetEquipments(categoryName, equipmentName string, size, offset int) (equipments []model.Equipment, count int64, err error) {
	//原生sql
	//SELECT e.* FROM equipments e JOIN equipment_categories ec ON e.category_id=ec.category_id
	//WHERE e.`name` LIKE '%%' and ec.`name` like '%健%';

	// 要获取总记录数，我们需要执行一个查询
	if err = mysql.Conn.Table("equipments").
		Joins("JOIN equipment_categories ec ON equipments.category_id = ec.category_id").
		Where("equipments.status = ?", "正常").
		Where("equipments.name LIKE ?", "%"+equipmentName+"%").
		Where("ec.name LIKE ?", "%"+categoryName+"%").
		Count(&count).Error; err != nil {
		zap.L().Error("Failed to get total count", zap.Error(err))
		return
	}

	if err = mysql.Conn.Model(&model.Equipment{}).
		Joins("left JOIN equipment_categories ec ON equipments.category_id = ec.category_id").
		Where("equipments.status = ?", "正常").
		Where("equipments.name LIKE ?", "%"+equipmentName+"%").
		Where("ec.name LIKE ?", "%"+categoryName+"%").
		Order("create_time desc").
		Limit(size).Offset(offset).
		Find(&equipments).Error; err != nil {
		zap.L().Error("GetUsers() failed", zap.Error(err))
		return
	}
	return equipments, count, err
}

func GetEquipmentInfo(equipmentId int) (equipment model.Equipment, err error) {
	if err = mysql.Conn.Model(&model.Equipment{}).Where("equipment_id=?", equipmentId).Where("status = ?", "正常").First(&equipment).Error; err != nil {
		zap.L().Error("GetEquipmentInfo(equipmentId int) Failed", zap.Error(err))
		return
	}
	return equipment, nil
}

func UpdateQuantity(equipmentId int, quantity int32) (err error) {
	if err = mysql.Conn.Model(&model.Equipment{}).Where("equipment_id=?", equipmentId).Update("quantity", quantity).Error; err != nil {
		zap.L().Error("UpdateQuantity(equipmentId int,quantity int32) Failed", zap.Error(err))
		return
	}
	return nil
}

func GetEquipmentBookingsByTimeRange(equipmentID int, startDate, endDate time.Time) (bookings []model.ReservationRequest, err error) {
	//已经被预定的总数量
	if err = mysql.Conn.Table("reservation_requests").
		Where("equipment_id=? and status='预定中'", equipmentID).
		Where("(start_time > ? and start_time < ?) or (end_time > ? and end_time< ?)", startDate, endDate, startDate, endDate).
		Find(&bookings).Error; err != nil {
		zap.L().Error("GetEquipmentBookingsByTimeRange(...) failed")
		return
	}
	return bookings, nil
}

func BookEquipments(book model.ReservationRequest) (err error) {
	if err = mysql.Conn.Table("reservation_requests").Save(&book).Error; err != nil {
		zap.L().Error("BookEquipments(book model.ReservationRequest) failed")
		return
	}
	return nil
}

func CancelBookEquipments(equipmentId int, userId int32, bookCount int, startDate, endDate time.Time) (err error) {
	if err = mysql.Conn.Table("reservation_requests").
		Where("equipment_id=? and user_id=? and status='预定中' and request_count=? and start_time=? and end_time=?", equipmentId, userId, bookCount, startDate, endDate).
		Update("status", "取消预定").Error; err != nil {
		zap.L().Error("BookEquipments(book model.ReservationRequest) failed")
		return
	}
	return nil
}

func IsBookEquipments(equipmentId int, userId int32, borrowCount int, startDate, endDate time.Time) bool {
	var reservationRequest *model.ReservationRequest
	if err := mysql.Conn.Table("reservation_requests").
		Where("equipment_id=? and user_id=? and status='预定中' and request_count=? and start_time=? and end_time=?", equipmentId, userId, borrowCount, startDate, endDate).
		First(&reservationRequest).Error; err != nil {
		zap.L().Error("BookEquipments(book model.ReservationRequest) failed")
		return false
	}
	if reservationRequest == nil {
		zap.L().Error("没有预定")
		return false
	}
	return true
}

func CompleteBookEquipments(equipmentId int, userId int32, bookCount int, startDate, endDate time.Time) (err error) {
	if err = mysql.Conn.Table("reservation_requests").
		Where("equipment_id=? and user_id=? and status='预定中' and request_count=? and start_time=? and end_time=?", equipmentId, userId, bookCount, startDate, endDate).
		Update("status", "完成").Error; err != nil {
		zap.L().Error("BookEquipments(book model.ReservationRequest) failed")
		return
	}
	return nil
}

func BorrowEquipments(borrow model.BorrowRecord) (err error) {
	if err = mysql.Conn.Table("borrow_records").Save(&borrow).Error; err != nil {
		zap.L().Error("BorrowEquipments(borrow model.BorrowRecord) failed")
		return err
	}
	return nil
}

func ReturnEquipments(equipmentId int, userId int32, borrowCount int, startDate, endDate time.Time) (err error) {
	if err = mysql.Conn.Table("borrow_records").
		Where("equipment_id=? and user_id=? and status='借阅' and borrow_count=? and borrow_time=? and return_time=?", equipmentId, userId, borrowCount, startDate, endDate).
		Update("status", "归还").Error; err != nil {
		zap.L().Error("ReturnEquipments(...) failed")
		return
	}
	return nil
}

func GetBorrowRecord(userId int32, equipmentName string, size, offset int) (borrowRecords []model.BorrowRecord, count int64, err error) {
	// 要获取总记录数，我们需要执行一个查询
	if err = mysql.Conn.Table("borrow_records").
		Where("user_id=?", userId).
		Where("name LIKE ?", "%"+equipmentName+"%").
		Count(&count).Error; err != nil {
		zap.L().Error("Failed to get total count", zap.Error(err))
		return
	}

	if err = mysql.Conn.Table("borrow_records").
		Where("user_id=?", userId).
		Where("name LIKE ?", "%"+equipmentName+"%").
		Order("borrow_time DESC").
		Limit(size).Offset(offset).
		Find(&borrowRecords).Error; err != nil {
		zap.L().Error("GetBorrowRecord(...) failed", zap.Error(err))
		return
	}
	return borrowRecords, count, err
}

func DeleteEquipment(equipmentId int) (err error) {
	if err = mysql.Conn.Model(&model.Equipment{}).
		Where("equipment_id=?", equipmentId).
		Update("status", "删除").Error; err != nil {
		zap.L().Error("DeleteEquipment(...) failed")
		return
	}
	return nil
}

func GetEquipmentCategoryName() (categoryName []string, err error) {
	if err = mysql.Conn.Model(&model.EquipmentCategory{}).Select("name").
		Find(&categoryName).Error; err != nil {
		zap.L().Error("GetEquipmentCategoryName(...) failed")
		return
	}
	return categoryName, nil
}

func GetEquipmentCategoryIdByName(categoryName string) (id int32, err error) {
	if err = mysql.Conn.Model(&model.EquipmentCategory{}).Select("category_id").Where("name", categoryName).First(&id).Error; err != nil {
		zap.L().Error("添加器材失败", zap.Error(err))
		return 0, nil
	}
	return id, nil
}

func AddEquipment(equipment model.Equipment) (err error) {
	if err = mysql.Conn.Model(&model.Equipment{}).Save(&equipment).Error; err != nil {
		zap.L().Error("添加器材失败", zap.Error(err))
		return err
	}
	return nil
}

func GetEquipmentCategoryNameById(categoryId int32) (categoryName string) {
	if err := mysql.Conn.Model(&model.EquipmentCategory{}).Select("name").Where("category_id=?", categoryId).First(&categoryName).Error; err != nil {
		zap.L().Error("添加器材失败", zap.Error(err))
		return ""
	}
	return categoryName
}

func IsEquipment(equipmentName string) bool {
	var equipment *model.Equipment
	if err := mysql.Conn.Model(&model.Equipment{}).Where("name=?", equipmentName).First(&equipment).Error; err != nil {
		zap.L().Error("根据器材名查询器材失败", zap.Error(err))
		return false
	}
	if equipment == nil {
		return false
	}
	return true
}

func GetEquipmentSta(equipmentId int) (status string, err error) {
	if err = mysql.Conn.Table("reservation_requests").Select("status").
		Where("equipment_id=?", equipmentId).
		First(&status).Error; err != nil {
		zap.L().Error("IsReturnEquipments(...) failed")
		return "", err
	}
	return status, nil
}

func GetEquipmentStatus(equipmentId int) (status string, err error) {
	if err = mysql.Conn.Table("borrow_records").Select("status").
		Where("equipment_id=?", equipmentId).
		First(&status).Error; err != nil {
		zap.L().Error("IsReturnEquipments(...) failed")
		return "", err
	}
	return status, nil
}

func GetAllBorrowRecord(equipmentName string, size, offset int) (borrowRecords []model.BorrowRecord, count int64, err error) {
	// 要获取总记录数，我们需要执行一个查询
	if err = mysql.Conn.Table("borrow_records").
		Where("name LIKE ?", "%"+equipmentName+"%").
		Count(&count).Error; err != nil {
		zap.L().Error("Failed to get total count", zap.Error(err))
		return
	}

	if err = mysql.Conn.Table("borrow_records").
		Where("name LIKE ?", "%"+equipmentName+"%").
		Order("borrow_time DESC").
		Limit(size).Offset(offset).
		Find(&borrowRecords).Error; err != nil {
		zap.L().Error("GetBorrowRecord(...) failed", zap.Error(err))
		return
	}
	return borrowRecords, count, err
}
